package com.eedi.framework.permission.convert;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.eedi.framework.permission.controller.org.vo.menu.OrgMenuResp;
import com.eedi.framework.permission.controller.org.vo.menu.OrgMenuSimpleResp;
import com.eedi.framework.permission.dal.dataobject.OrgMenuDO;
import com.eedi.framework.permission.enums.OrgMenuTypeEnum;
import com.eedi.framework.template.dal.dataobject.SysTemplateMenuDO;
import com.eedi.framework.template.enums.SysTemplateMenuTypeEnum;
import org.mapstruct.Mapper;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

import java.util.*;

import static com.eedi.framework.common.util.collection.CollectionUtils.filterList;
import static com.eedi.framework.permission.dal.dataobject.OrgMenuDO.ORG_ID_ROOT;

/**
 * @author zybourn
 */
@Mapper
public interface OrgMenuConvert {
    OrgMenuConvert INSTANCE = Mappers.getMapper(OrgMenuConvert.class);


    OrgMenuSimpleResp convert(OrgMenuResp resp);

    OrgMenuDO convertDO(OrgMenuResp orgMenuResps);

    List<OrgMenuDO> convertDO(Collection<OrgMenuResp> orgMenuResps);


    /**
     * 将菜单列表，构建成菜单树
     *
     * @param menuList 菜单列表
     * @return 菜单树
     */
    default List<OrgMenuSimpleResp> buildMenuSimpleTree(List<OrgMenuSimpleResp> menuList) {
        if (CollUtil.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 移除按钮
//        menuList.removeIf(menu -> menu.getSysMenuType().equals(SysMenuTypeEnum.BUTTON));
        // 排序，保证菜单的有序性
        menuList.sort(Comparator.comparing(OrgMenuSimpleResp::getOrgMenuSort));
        // 构建菜单树
        // 使用 LinkedHashMap 的原因，是为了排序 。实际也可以用 Stream API ，就是太丑了。
        Map<String, OrgMenuSimpleResp> treeNodeMap = new LinkedHashMap<>();
        menuList.forEach(menu -> treeNodeMap.put(menu.getOrgMenuId(), menu));
        // 处理父子关系
        treeNodeMap.values().stream().filter(node -> !node.getParentOrgMenuId().equals(ORG_ID_ROOT)).forEach(childNode -> {
            // 获得父节点
            OrgMenuSimpleResp parentNode = treeNodeMap.get(childNode.getParentOrgMenuId());
            if (parentNode == null) {
                return;
            }
            // 将自己添加到父节点中
            if (parentNode.getChildren() == null) {
                parentNode.setChildren(new ArrayList<>());
            }
            parentNode.getChildren().add(childNode);
        });
        // 获得到所有的根节点
        return filterList(treeNodeMap.values(), node -> ORG_ID_ROOT.equals(node.getParentOrgMenuId()));
    }


    /**
     * 将菜单列表，构建成菜单树
     *
     * @param menuList 菜单列表
     * @return 菜单树
     */
    default List<OrgMenuResp> buildMenuTree(List<OrgMenuResp> menuList) {
        if (CollUtil.isEmpty(menuList)) {
            return Collections.emptyList();
        }
        // 移除按钮
//        menuList.removeIf(menu -> menu.getSysMenuType().equals(SysMenuTypeEnum.BUTTON));
        // 排序，保证菜单的有序性
        menuList.sort(Comparator.comparing(OrgMenuResp::getOrgMenuSort));
        // 构建菜单树
        // 使用 LinkedHashMap 的原因，是为了排序 。实际也可以用 Stream API ，就是太丑了。
        Map<String, OrgMenuResp> treeNodeMap = new LinkedHashMap<>();
        menuList.forEach(menu -> treeNodeMap.put(menu.getOrgMenuId(), menu));
        // 处理父子关系
        treeNodeMap.values().stream().filter(node -> !node.getParentOrgMenuId().equals(ORG_ID_ROOT)).forEach(childNode -> {
            // 获得父节点
            OrgMenuResp parentNode = treeNodeMap.get(childNode.getParentOrgMenuId());
            if (parentNode == null) {
                return;
            }
            // 将自己添加到父节点中
            if (parentNode.getChildren() == null) {
                parentNode.setChildren(new ArrayList<>());
            }
            parentNode.getChildren().add(childNode);
        });
        // 获得到所有的根节点
        return filterList(treeNodeMap.values(), node -> ORG_ID_ROOT.equals(node.getParentOrgMenuId()));
    }

    List<OrgMenuResp> convert(Collection<SysTemplateMenuDO> sysMenus);

    List<OrgMenuResp> convertOrgMenuResp(Collection<SysTemplateMenuDO> sysMenu);

    default OrgMenuResp convertOrgMenuResp(SysTemplateMenuDO sysMenu){
        if (ObjectUtil.isEmpty(sysMenu)){
            return null;
        }
        OrgMenuResp orgMenu= new OrgMenuResp();
        orgMenu.setOrgMenuId(sysMenu.getSysTemplateMenuId())
                .setOrgMenuName(sysMenu.getSysMenuName())
                .setOrgMenuPermission(sysMenu.getSysMenuPermission())
                .setOrgMenuType(sysTemplateMenuTypeToOrgMenuType(sysMenu.getSysMenuType()))
                .setOrgMenuSort(sysMenu.getSysMenuSort())
                .setParentOrgMenuId(sysMenu.getParentSysMenuId())
                .setOrgMenuPath(sysMenu.getSysMenuPath())
                .setOrgMenuIcon(sysMenu.getSysMenuIcon())
                .setOrgMenuComponent(sysMenu.getSysMenuComponent())
                .setOrgMenuComponentName(sysMenu.getSysMenuComponentName())
                .setOrgMenuStatus(sysMenu.getSysMenuStatus())
                .setOrgMenuVisible(sysMenu.getSysMenuVisible())
                .setOrgMenuKeepAlive(sysMenu.getSysMenuKeepAlive())
                .setOrgMenuAlwaysShow(sysMenu.getSysMenuAlwaysShow());
        return orgMenu;
    }



   default OrgMenuDO convert(SysTemplateMenuDO sysMenu){
        if (ObjectUtil.isEmpty(sysMenu)){
            return null;
        }
       OrgMenuDO orgMenu= new OrgMenuDO();
       orgMenu.setOrgMenuId(sysMenu.getSysTemplateMenuId())
               .setOrgMenuName(sysMenu.getSysMenuName())
               .setOrgMenuPermission(sysMenu.getSysMenuPermission())
               .setOrgMenuType(sysTemplateMenuTypeToOrgMenuType(sysMenu.getSysMenuType()))
               .setOrgMenuSort(sysMenu.getSysMenuSort())
               .setParentOrgMenuId(sysMenu.getParentSysMenuId())
               .setOrgMenuPath(sysMenu.getSysMenuPath())
               .setOrgMenuIcon(sysMenu.getSysMenuIcon())
               .setOrgMenuComponent(sysMenu.getSysMenuComponent())
               .setOrgMenuComponentName(sysMenu.getSysMenuComponentName())
               .setOrgMenuStatus(sysMenu.getSysMenuStatus())
               .setOrgMenuVisible(sysMenu.getSysMenuVisible())
               .setOrgMenuKeepAlive(sysMenu.getSysMenuKeepAlive())
               .setOrgMenuAlwaysShow(sysMenu.getSysMenuAlwaysShow());
       return orgMenu;
   }


    @Named("sysTemplateMenuTypeToOrgMenuType")
    default OrgMenuTypeEnum sysTemplateMenuTypeToOrgMenuType(SysTemplateMenuTypeEnum sysTemplateMenuTypeEnum){
        if (ObjectUtil.isEmpty(sysTemplateMenuTypeEnum)){
            return null;
        }
        return OrgMenuTypeEnum.getByCode(sysTemplateMenuTypeEnum.getCode());
    }
}
